package com.xiaolei.library.Base;

import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.PopupWindow;

import androidx.annotation.FloatRange;
import androidx.annotation.IdRes;
import androidx.annotation.IntDef;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.fragment.app.Fragment;

import com.xiaolei.library.Exts.Ext;
import com.xiaolei.library.R;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 弹出框的基类
 */
public abstract class BasePopupWindow extends PopupWindow
{
    public static final int IN_BOTTOM = 0x02;
    public static final int IN_TOP = 0x04;
    public static final int IN_LEFT = 0x06;
    public static final int IN_RIGHT = 0x08;
    public static final int CENTER = 0x10;
    public static final int OUT_BOTTOM = 0x12;
    public static final int OUT_TOP = 0x14;
    public static final int OUT_LEFT = 0x16;
    public static final int OUT_RIGHT = 0x18;


    @IntDef({IN_BOTTOM, IN_TOP, IN_LEFT, IN_RIGHT,
            CENTER,
            OUT_BOTTOM, OUT_TOP, OUT_LEFT, OUT_RIGHT
    })
    @Target({ElementType.PARAMETER}) //表示注解作用范围，参数注解，成员注解，方法注解
    @Retention(RetentionPolicy.SOURCE) //表示注解所存活的时间,在运行时,而不会存在 .class 文件中
    public @interface Position
    {
    }


    // 布局
    private int layoutRes;
    // 真正显示的控件
    private ViewGroup view;
    // 宽度
    private int width = WindowManager.LayoutParams.WRAP_CONTENT;
    // 高度
    private int height = WindowManager.LayoutParams.WRAP_CONTENT;
    // 自动透明度调整的属性
    private float autoAlpha = 1;
    // 最后一个附属的控件
    private Activity lastActivity = null;
    // 外部是否可以点击
    private boolean outSideTouchable = true;
    // 是否有焦点
    private boolean focusable = false;
    // 背景
    private Drawable backgroundDrawable = null;
    // 隐藏的事件
    private OnDismissListener onDismissListener;
    // 降低透明度的耗时
    private long alphaDuration = 200;
    // 动画的速度控制
    private TimeInterpolator interpolator = new LinearInterpolator();
    // 动画的监听器
    private ValueAnimator.AnimatorUpdateListener animatorUpdateListener;
    // 进入，推出动画的资源文件
    private int animationStyle = -1;
    // 初始化动画
    private ValueAnimator animator = new ValueAnimator();

    public BasePopupWindow(@LayoutRes int layoutRes)
    {
        this.layoutRes = layoutRes;
    }

    /**
     * 初始化
     *
     * @param context
     */
    private synchronized void init(Context context)
    {
        if (view == null)
        {
            LayoutInflater inflater = LayoutInflater.from(context);
            // 预先使用一个父布局
            view = new FrameLayout(context);
            // 根据父布局，实例化子布局
            View childView = inflater.inflate(layoutRes, view, false);
            // 将子布局加入父布局
            view.addView(childView);
            // 是否可以有焦点
            super.setFocusable(focusable);
            // 是否外部可以点
            super.setOutsideTouchable(outSideTouchable);
            // 设置宽度
            super.setWidth(width);
            // 设置高度
            super.setHeight(height);
            // 设备背景
            super.setBackgroundDrawable(backgroundDrawable);
            // 设置默认的动画效果
            super.setAnimationStyle(R.style.BaseAnimStyle);
            // 设置视图
            setContentView(view);

            initView(childView);

            // 测量视图
            getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
            initEvent();
            loadData();
            // 设置控件消失的事件
            super.setOnDismissListener(new OnDismissListener()
            {
                @Override
                public void onDismiss()
                {
                    if (lastActivity != null)
                    {
                        Ext.setAlpha(lastActivity, 1);
                        lastActivity = null;
                    }
                    if (animator.isRunning())
                    {
                        animator.cancel();
                    }
                    if (onDismissListener != null)
                    {
                        onDismissListener.onDismiss();
                    }
                    BasePopupWindow.this.onDismiss();
                }
            });
        }
    }

    /**
     * 设置宽度，可以使用 WindowManager.LayoutParams.WRAP_CONTENT,也可以使用精准的数字
     *
     * @param width
     */
    @Override
    public void setWidth(int width)
    {
        this.width = width;
    }

    /**
     * 设置高度，可以使用 WindowManager.LayoutParams.WRAP_CONTENT,也可以使用精准的数字
     *
     * @param height
     */
    @Override
    public void setHeight(int height)
    {
        this.height = height;
    }

    /**
     * 当弹出来的时候，activity 显示，那么自动徐徐降低到这个透明度
     *
     * @param alpha
     */
    public void autoAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha)
    {
        this.autoAlpha = alpha;
    }

    /**
     * 当弹出来的时候，activity 显示，那么自动徐徐降低到这个透明度
     *
     * @param alpha
     */
    public void autoAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha, long duration)
    {
        this.alphaDuration = duration;
        this.autoAlpha = alpha;
    }

    /**
     * 外部是否可以点击
     *
     * @param touchable
     */
    @Override
    public void setOutsideTouchable(boolean touchable)
    {
        this.outSideTouchable = touchable;
    }

    /**
     * 是否设置焦点
     *
     * @param focusable
     */
    @Override
    public void setFocusable(boolean focusable)
    {
        this.focusable = focusable;
    }

    /**
     * 设置背景图
     *
     * @param backgroundDrawable
     */
    @Override
    public void setBackgroundDrawable(@Nullable Drawable backgroundDrawable)
    {
        this.backgroundDrawable = backgroundDrawable;
    }

    /**
     * 设置控件隐藏事件
     *
     * @param onDismissListener
     */
    @Override
    public void setOnDismissListener(OnDismissListener onDismissListener)
    {
        this.onDismissListener = onDismissListener;
    }

    /**
     * 设置进出动画风格
     *
     * @param animationStyle
     */
    @Override
    public void setAnimationStyle(@StyleRes int animationStyle)
    {
        this.animationStyle = animationStyle;
    }

    /**
     * 初始化控件
     *
     * @param view
     */
    public abstract void initView(@NonNull View view);

    /**
     * 初始化事件
     */
    public abstract void initEvent();

    /**
     * 加载数据
     */
    public abstract void loadData();

    /**
     * 控件隐藏的事件
     */
    public void onDismiss()
    {
    }

    /**
     * 设置点击外部事件
     *
     * @param dismiss 是否隐藏
     * @param through 是否触摸穿透
     */
    public void setTouchOutSide(boolean dismiss, boolean through)
    {
        backgroundDrawable = new ColorDrawable(Color.TRANSPARENT);
        if (dismiss)
        {
            focusable = true;
        } else
        {
            focusable = !through;
            setTouchInterceptor(new View.OnTouchListener()
            {
                @Override
                public boolean onTouch(View v, MotionEvent event)
                {
                    return true;
                }
            });
        }
    }

    public <T extends View> T findViewById(@IdRes int id)
    {
        if (view == null)
        {
            throw new RuntimeException("BasePopupWindow'findViewById have to invoke after call show()");
        }
        return view.findViewById(id);
    }


    /**
     * 基于 activity 的显示
     *
     * @param activity
     * @param pos
     */
    public void show(@NonNull Activity activity, @Position int pos)
    {
        View decorView = activity.findViewById(android.R.id.content);
        lastActivity = activity;
        show(decorView, pos);
    }

    /**
     * 基于 fragment 的显示
     *
     * @param fragment
     * @param pos
     */
    public void show(@NonNull Fragment fragment, @Position int pos)
    {
        View view = fragment.requireView();
        lastActivity = fragment.requireActivity();
        show(view, pos);
    }

    /**
     * 基于 某个控件的显示
     *
     * @param view 依据的控件
     * @param pos  位置
     */
    public void show(@NonNull View view, @Position int pos)
    {
        init(view.getContext());
        int viewHeight = view.getMeasuredHeight();
        int viewWidth = view.getMeasuredWidth();
        int selfHeight = getContentView().getMeasuredHeight();
        int selfWidth = getContentView().getMeasuredWidth();

        int animationStyle = R.style.BaseAnimStyle;
        int xoff = 0;
        int yoff = 0;

        switch (pos)
        {
            case IN_BOTTOM:
            {
                animationStyle = R.style.BaseAnimStyle_BOTTOM_2_UP;
                xoff = viewWidth / 2 - selfWidth / 2;
                yoff = -selfHeight;
            }
            break;
            case IN_TOP:
            {
                animationStyle = R.style.BaseAnimStyle_UP_2_BOTTOM;
                xoff = viewWidth / 2 - selfWidth / 2;
                yoff = -viewHeight;
            }
            break;
            case IN_LEFT:
            {
                animationStyle = R.style.BaseAnimStyle_LEFT_2_RIGHT;
                xoff = 0;
                yoff = -viewHeight / 2 - selfHeight / 2;
            }
            break;
            case IN_RIGHT:
            {
                animationStyle = R.style.BaseAnimStyle_RIGHT_2_LEFT;
                xoff = viewWidth - selfWidth;
                yoff = -viewHeight / 2 - selfHeight / 2;
            }
            break;
            case OUT_BOTTOM:
            {
                animationStyle = R.style.BaseAnimStyle_UP_2_BOTTOM;
                xoff = viewWidth / 2 - selfWidth / 2;
                yoff = 0;
            }
            break;
            case OUT_TOP:
            {
                animationStyle = R.style.BaseAnimStyle_BOTTOM_2_UP;
                xoff = viewWidth / 2 - selfWidth / 2;
                yoff = -viewHeight - selfHeight;
            }
            break;
            case OUT_LEFT:
            {
                animationStyle = R.style.BaseAnimStyle_RIGHT_2_LEFT;
                xoff = -selfWidth;
                yoff = -viewHeight / 2 - selfHeight / 2;
            }
            break;
            case OUT_RIGHT:
            {
                animationStyle = R.style.BaseAnimStyle_LEFT_2_RIGHT;
                xoff = viewWidth;
                yoff = -viewHeight / 2 - selfHeight / 2;
            }
            break;
            case CENTER:
            {
                animationStyle = R.style.BaseAnimStyle;
                xoff = viewWidth / 2 - selfWidth / 2;
                yoff = -(viewHeight / 2 + selfHeight / 2);
            }
            break;
        }

        if (this.animationStyle != -1)
        {
            animationStyle = this.animationStyle;
        }
        super.setAnimationStyle(animationStyle);
        showAsDropDown(view, xoff, yoff);

        if (lastActivity != null)
        {
            if (animator.isRunning())
            {
                animator.cancel();
            }
            animator.setDuration(alphaDuration);
            animator.setFloatValues(1f, autoAlpha);
            animator.setInterpolator(interpolator);
            animator.addUpdateListener(initAnimatorListener());
            animator.start();
        }
    }

    /**
     * 初始化动画初始化的监听事件
     */
    private synchronized ValueAnimator.AnimatorUpdateListener initAnimatorListener()
    {
        if (animatorUpdateListener == null)
        {
            animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener()
            {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator)
                {
                    float alpha = (float) valueAnimator.getAnimatedValue();
                    if (lastActivity != null)
                    {
                        Ext.setAlpha(lastActivity, alpha);
                    }
                }
            };
        }
        return animatorUpdateListener;
    }

}
